package com.bsoft.gol.hcs.specialist.dao;

import ctd.controller.exception.ControllerException;
import ctd.persistence.annotation.DAOMethod;
import ctd.persistence.annotation.DAOParam;
import ctd.persistence.support.hibernate.HibernateSupportDelegateDAO;
import ctd.persistence.support.hibernate.template.AbstractHibernateStatelessResultAction;
import ctd.persistence.support.hibernate.template.HibernateSessionTemplate;
import ctd.persistence.support.hibernate.template.HibernateStatelessResultAction;
import ctd.util.converter.ConversionUtils;
import com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum;
import com.bsoft.gol.hcs.enumcase.FollowTypeEnum;
import org.hibernate.Query;
import org.hibernate.StatelessSession;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.transform.Transformers;
import com.bsoft.gol.hcs.specialist.bean.request.GroupChronicRecordQo;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialRecordResponse;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialTimeRecordList;
import com.bsoft.gol.hcs.specialist.bean.response.FactorData;
import com.bsoft.gol.hcs.specialist.entity.FollowUpRouteDetailFactorRelation;
import com.bsoft.gol.hcs.specialist.entity.FusAnswerInspectionReportInfo;
import com.bsoft.gol.hcs.utils.CommonUtils;

import java.util.*;

import static com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum.*;

/**
 * @author tongtp
 * @version v0.1
 * @className FusAnswerInspectionReportInfoDAO
 * @description
 * @create 2020-07-31 15:08
 **/
public abstract class FusAnswerInspectionReportInfoDAO extends HibernateSupportDelegateDAO<FusAnswerInspectionReportInfo> {

    /**
     * @param reportId
     * @throws
     * @description: 根据表单答案唯一记录id查询
     * @return: specialist.entity.FusAnswerInspectionReportInfo
     * @author: tongtp
     * @date: 2020/8/4 17:57
     */
    @DAOMethod(sql = " from FusAnswerInspectionReportInfo where reportId = :reportId")
    public abstract FusAnswerInspectionReportInfo getByReportId(@DAOParam("reportId") String reportId);

    /**
     * @param answerTime
     * @throws
     * @description: 更新检验报告指标结果内容
     * @return: java.util.List<java.lang.Long>
     * @author: tongtp
     * @date: 2020/7/31 16:59
     */
    public Integer updateIndexResultContent(final Date answerTime) {
        HibernateStatelessResultAction<Integer> action =
                new AbstractHibernateStatelessResultAction<Integer>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("update fus_answer_inspection_report_info AS a set a.index_result_content " +
                                "=" +
                                " " +
                                "(select b.index_result_content from fus_index_result AS b where b.index_id = a" +
                                ".item_id AND b.index_result_type = 2 AND b.index_description = a.result) where " +
                                "index_result_content IS NULL AND a" +
                                ".answer_time" +
                                " " +
                                ">= :answerTime");

                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("answerTime", answerTime);

                        int executeUpdate = query.executeUpdate();

                        sqlBuilder.setLength(0);
                        sqlBuilder.append("update fus_answer_inspection_report_info AS a set a.index_result_content " +
                                "=" +
                                " " +
                                "(select b.index_result_content from fus_index_result AS b where b.index_id = a" +
                                ".item_id AND b.index_result_type = 1 AND b.lower_limit <= a.result AND b" +
                                ".upper_limit" +
                                " " +
                                ">= a.result) where index_result_content IS NULL AND a" +
                                ".answer_time" +
                                " " +
                                ">= :answerTime");
                        query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("answerTime", answerTime);

                        executeUpdate += query.executeUpdate();

                        setResult(executeUpdate);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 获取检验的关联指标信息
     *
     * @param qo
     * @return
     */
    public List<CrucialRecordResponse> queryAnswerInspectionReportInfo(GroupChronicRecordQo qo) {
        HibernateStatelessResultAction<List<CrucialRecordResponse>> action = new AbstractHibernateStatelessResultAction<List<CrucialRecordResponse>>() {
            @Override
            public void execute(StatelessSession ss) throws Exception {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("SELECT DISTINCT fa.item_id AS indexType,fa.item_name AS indexName FROM fus_answer_inspection_report_info fa,fus_index_result fr WHERE fa.item_id = fr.index_id and fa.patient_id =:patientId and fa.disease_type_id =:diseaseTypeId ");
                sqlBuilder.append(" and fa.create_time >=:beginTime and fa.create_time <=:endTime group by fa.item_id,fa.item_name");
                Query query = ss.createSQLQuery(sqlBuilder.toString());
                query.setParameter("patientId", qo.getPatientId());
                query.setParameter("diseaseTypeId", qo.getDiseaseTypeId());
                query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = query.list();
                List<CrucialRecordResponse> voList = new ArrayList<>();
                if (CommonUtils.isNotEmpty(list)) {
                    for (Map map : list) {
                        voList.add(ConversionUtils.convert(map, CrucialRecordResponse.class));
                    }
                } else {
                    voList = new ArrayList<>();
                }
                setResult(voList);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<CrucialTimeRecordList> queryAnswerInspectionReportTimeInfo(GroupChronicRecordQo qo, String itemCode) {
        HibernateStatelessResultAction<List<CrucialTimeRecordList>> action = new AbstractHibernateStatelessResultAction<List<CrucialTimeRecordList>>() {
            @Override
            public void execute(StatelessSession ss) throws Exception {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("SELECT DISTINCT " +
                        " fa.item_id AS indexType, " +
                        " fa.item_name AS indexName, " +
                        " fa.result AS indexResultContent, " +
                        " fa.ref_range AS refRange, " +
                        " fa.result AS indexValue, " +
                        " fa.sample_test_time AS crucialTime  " +
                        "FROM " +
                        " fus_answer_inspection_report_info fa, " +
                        " fus_index_result fr  " +
                        "WHERE " +
                        " fa.item_id = fr.index_id and fa.item_id=:itemCode and fa.patient_id =:patientId and fa.disease_type_id =:diseaseTypeId ");
                sqlBuilder.append(" and fa.create_time >=:beginTime and fa.create_time <=:endTime order by fa.create_time ");
                Query query = ss.createSQLQuery(sqlBuilder.toString());
                query.setParameter("itemCode", itemCode);
                query.setParameter("patientId", qo.getPatientId());
                query.setParameter("diseaseTypeId", qo.getDiseaseTypeId());
                query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = query.list();
                List<CrucialTimeRecordList> voList = new ArrayList<>();
                if (CommonUtils.isNotEmpty(list)) {
                    for (Map map : list) {
                        voList.add(ConversionUtils.convert(map, CrucialTimeRecordList.class));
                    }
                } else {
                    voList = new ArrayList<>();
                }
                setResult(voList);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 根据用户和病种查询ReportId
     *
     * @param diseaseTypeId
     * @param patientId
     * @param patientMedicalCardType
     * @param patientMedicalCardNumber
     * @param cardType
     * @param cardNumber
     * @return java.util.List<java.lang.String>
     * @throws
     * @author tongtp
     * @date 2021/12/29 13:41
     */
    public List<String> queryReportId(Long diseaseTypeId, String patientId,
                                      Integer patientMedicalCardType, String patientMedicalCardNumber,
                                      String cardType, String cardNumber) {
        HibernateStatelessResultAction<List<String>> action =
                new AbstractHibernateStatelessResultAction<List<String>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("select report_id from fus_answer_inspection_report_info" +
                                "  where disease_type_id = :diseaseTypeId ");
                        sqlBuilder.append(" and ( ");
                        if (CommonUtils.isNotNull(patientId)) {
                            sqlBuilder.append(" patient_id = :patientId ");
                        }
                        if (CommonUtils.isNotNull(patientMedicalCardType) && CommonUtils.isNotNull(patientMedicalCardNumber)) {
                            sqlBuilder.append("  or (patient_medical_card_type = :patientMedicalCardType and" +
                                    " patient_medical_card_number = :patientMedicalCardNumber) ");
                        }
                        if (CommonUtils.isNotNull(cardType) && CommonUtils.isNotNull(cardNumber)) {
                            sqlBuilder.append("  or (card_type = :cardType and" +
                                    " card_number = :cardNumber) ");
                        }
                        sqlBuilder.append(" ) ");
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("diseaseTypeId", diseaseTypeId);
                        if (CommonUtils.isNotNull(patientId)) {
                            query.setParameter("patientId", patientId);
                        }
                        if (CommonUtils.isNotNull(patientMedicalCardType) && CommonUtils.isNotNull(patientMedicalCardNumber)) {
                            query.setParameter("patientMedicalCardType", patientMedicalCardType);
                            query.setParameter("patientMedicalCardNumber", patientMedicalCardNumber);
                        }
                        if (CommonUtils.isNotNull(cardType) && CommonUtils.isNotNull(cardNumber)) {
                            query.setParameter("cardType", cardType);
                            query.setParameter("cardNumber", cardNumber);
                        }
                        List list = query.list();
                        List<String> voList;
                        if (CommonUtils.isNotEmpty(list)) {
                            voList = list;
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<FactorData> executeFactorForRelatedIndicators(FollowUpRouteDetailFactorRelation factorRelation, Date startTime, Date endTime, List<String> patientIdList, Byte isLoopExecute, Long routeDetailId, String followType) {
        HibernateStatelessResultAction<List<FactorData>> action =
                new AbstractHibernateStatelessResultAction<List<FactorData>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("select patientId,indexRecordId,indexCode,indexName ,indexResult," +
                                "reportTime,dataSource from ( ");
                        //因素内容性质类型，1定量，2定性 3 文本,因素类型为关联指标必填
                        Byte factorNatureType = factorRelation.getFactorNatureType();
                        sqlBuilder.append("SELECT  a.patient_id AS patientId, '2' AS dataSource,");
                        sqlBuilder.append("a.item_id AS indexRecordId, a.specimen_type_id AS indexCode, a" +
                                ".specimen_type_name AS indexName, ");
                        sqlBuilder.append("a.result AS indexResult, ");
                        sqlBuilder.append("a.report_time AS reportTime ");
                        sqlBuilder.append("FROM fus_answer_inspection_report_info AS a  ");
                        sqlBuilder.append("where a.specimen_type_id = :indexResultId and a.report_time >= " +
                                ":recordStartTime and a.report_time <= :recordEndTime ");

                        //条件筛选方法：1 范围(包含边界) 2 等于 3 大于 4 小于 5 大于等于 6 小于等于，7包含，8不包含 9 Between
                        Byte conditionFilterMethod = Byte.valueOf(factorRelation.getCompareSign());
                        ConditionFilterMethodEnum methodEnum = getEnumByKey(conditionFilterMethod);
                        if (factorNatureType != null && factorNatureType == 1) {
                            //定量结果
                            switch (methodEnum) {
                                case EQUAL:
                                    sqlBuilder.append(" and a.result = :factorResultOne");
                                    break;
                                case GREATER_THAN:
                                    sqlBuilder.append(" and a.result > :factorResultOne");
                                    break;
                                case LESS_THAN:
                                    sqlBuilder.append(" and a.result < :factorResultOne");
                                    break;
                                case GREATER_THAN_OR_EQUAL:
                                    sqlBuilder.append(" and a.result >= :factorResultOne");
                                    break;
                                case LESS_THAN_OR_EQUAL:
                                    sqlBuilder.append(" and a.result <= :factorResultOne");
                                    break;
                                case SCOPE:
                                case BETWEEN:
                                    sqlBuilder.append(" and a.result >= :factorResultOne and a.result <= " +
                                            ":factorResultTwo ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        } else if (factorNatureType != null && factorNatureType == 2) {
                            //定性结果-只会有包含in 和不包含 not in
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and a.result in (:factorResultList) ");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and a.result not in (:factorResultList) ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        } else {
                            //文本结果-只会有包含like 和不包含 not like
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and a.result like :factorResultOne ");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and a.result not like :factorResultOne ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            sqlBuilder.append(" and a.patient_id in (:patientIdList)");
                        }
                        sqlBuilder.append(") AS  m ");
                        //循环执行机制 0 不执行 1 执行
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            sqlBuilder.append(" LEFT JOIN fus_factor_data_record f  ON f.patient_id = m.patientId   " +
                                    "AND f.route_detail_id = :routeDetailId AND f.index_record_id = m.indexRecordId " +
                                    "WHERE f.id IS NULL  ");
                        }
                        Query query = ss.createSQLQuery(sqlBuilder.toString());

                        if (factorNatureType != null && factorNatureType == 1) {
                            //定量结果
                            String stringFactorResultOne = factorRelation.getFactorResultOne();
                            Long longFactorResultOne = null;
                            Double doubleFactorResultOne = null;
                            try {
                                doubleFactorResultOne =
                                        Double.valueOf(stringFactorResultOne);
                            } catch (Exception e) {
                                doubleFactorResultOne = null;
                                try {
                                    longFactorResultOne = Long.valueOf(stringFactorResultOne);
                                } catch (Exception e1) {
                                    longFactorResultOne = null;
                                }
                            }
                            if (doubleFactorResultOne != null) {
                                query.setParameter("factorResultOne", doubleFactorResultOne);
                            } else if (longFactorResultOne != null) {
                                query.setParameter("factorResultOne", longFactorResultOne);
                            } else {
                                query.setParameter("factorResultOne", stringFactorResultOne);
                            }
                            if (SCOPE.equals(methodEnum) || BETWEEN.equals(methodEnum)) {
                                String stringFactorResultTwo = factorRelation.getFactorResultTwo();
                                Long longFactorResultTwo = null;
                                Double doubleFactorResultTwo = null;
                                try {
                                    doubleFactorResultTwo =
                                            Double.valueOf(stringFactorResultTwo);
                                } catch (Exception e) {
                                    doubleFactorResultTwo = null;
                                    try {
                                        longFactorResultTwo = Long.valueOf(stringFactorResultTwo);
                                    } catch (Exception e1) {
                                        longFactorResultTwo = null;
                                    }
                                }
                                if (doubleFactorResultTwo != null) {
                                    query.setParameter("factorResultTwo", doubleFactorResultTwo);
                                } else if (longFactorResultTwo != null) {
                                    query.setParameter("factorResultTwo", longFactorResultTwo);
                                } else {
                                    query.setParameter("factorResultTwo", stringFactorResultTwo);
                                }
                            }
                        } else if (factorNatureType != null && factorNatureType == 2) {
                            //定性结果-只会有包含in 和不包含 not in
                            String[] strings = factorRelation.getFactorResultOne().split(",");
                            List<String> factorResultList = Arrays.asList(strings);
                            query.setParameterList("factorResultList", factorResultList);
                        } else {
                            //文本结果-只会有包含like 和不包含 not like
                            query.setParameter("factorResultOne", "%" + factorRelation.getFactorResultOne() + "%");
                        }

                        query.setParameter("indexResultId", factorRelation.getIndexResultId());
                        query.setParameter("recordStartTime", startTime);
                        query.setParameter("recordEndTime", endTime);
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            query.setParameterList("patientIdList", patientIdList);
                        }
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            query.setParameter("routeDetailId", routeDetailId);
                        }
                        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
                        List<Map> list = query.list();
                        List<FactorData> voList = new ArrayList<>();
                        if (CommonUtils.isNotEmpty(list)) {
                            for (Map map : list) {
                                voList.add(ConversionUtils.convert(map, FactorData.class));
                            }
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }
}
